package info.fastpace.android.utils.list;

import info.fastpace.utils.Decorator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class ListDataAdapter<T> extends BaseAdapter{

	private  List<T> items;// = new ArrayList<T>();
	
	protected LayoutInflater inflater;
	private int listItemRes;
	// NOT passed in constructor but using setter in order to create an instance
	// of the adapter and then pass it to a binder. Example: async support to
	// notify the adapter upon background processing complete (download
	// thumbnail)
	private Binder<T> binder = new Binder<T>() {
		@Override
		public void bind(T item, View view) {
			// DO NOTHING by default
		}
	};


	public ListDataAdapter(Context context, int listItemRes) {
		this(context, listItemRes, new ArrayList<T>());
	}

	public ListDataAdapter(Context context, int listItemRes, List<T> items) {
		this.listItemRes = listItemRes;
// 		Tried this because saw in stackoverflow (http://stackoverflow.com/questions/6130691/issue-displaying-a-custom-alert-dialog)
//		that creating LayoutInflater in different ways give different results.
//		It was in the context of list items in alert dialog - the text was gray instead of black - when popped up from the SimpleImageViewer
//		Didn't work though :(
//		if (context instanceof Activity) {
//			inflater = ((Activity)context).getLayoutInflater();
//		}else {
//			inflater = LayoutInflater.from(context);
//		}
		inflater = LayoutInflater.from(context);
		this.items = items;
		
	}
	
	public void setItems(List<? extends T> items) {
		this.items = new ArrayList<T>();
		this.items.addAll(items);
		notifyDataSetChanged();
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			convertView = inflater.inflate(listItemRes, parent, false);
		}

		binder.bind(getItem(position), convertView);

		return convertView;
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public T getItem(int position) {
		return items.get(position);
	}

	@Override
	public int getCount() {
		return items.size();
	}

	public void setBinder(Binder<T> binder) {
		this.binder = binder;
	}

	public void addAll(Collection<T> items) {
		this.items.addAll(items);
		notifyDataSetChanged();
	}
	
	public void add(T item) {
		this.items.add(item);
		notifyDataSetChanged();
	}
	
	public void remove(T item) {
		items.remove(item);
		notifyDataSetChanged();
	}

	public List<T> getItems() {
		return Collections.unmodifiableList(items);
	}

	
	public interface Binder<T> {
		void bind(T item, View view);
		
		public static class Util {
			private Util() {}
			public static class BinderDecorator<T, B extends Binder<T>> extends Decorator<B> implements Binder<T> {
				public BinderDecorator(B b) {
					super(b);
				}
				@Override
				public void bind(T item, View view) {
					getInner().bind(item, view);
				}
			}
			public static class BinderDecoratorSimple<T> extends BinderDecorator<T, Binder<T>> {
				public BinderDecoratorSimple(Binder<T> b) {
					super(b);
				}
			}
			public static class BinderEmpty<T> implements Binder<T> {
				@Override
				public void bind(T item, View view) {
					// Do nothing
				}
			}
		}
	}
	
}
